package com.xxxx.spring.day12;

import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.StaticMethodMatcherPointcut;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Method;

public class D12 {

    public static void main(String[] args) throws NoSuchMethodException {
        // 1 2 只能匹配方法的信息 和 @Transactional 加在类上 接口上还是有区别的

        // 1、方法名字匹配
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression("execution(* bar())");
        // 判断方法是否有被 切点 匹配到
        System.out.println(pointcut.matches(T1.class.getMethod("foo"),T1.class));
        System.out.println(pointcut.matches(T1.class.getMethod("bar"),T1.class));

        System.out.println("==================");

        // 2、注解匹配
        AspectJExpressionPointcut pt2 = new AspectJExpressionPointcut();
        pt2.setExpression("@annotation(org.springframework.transaction.annotation.Transactional)");
        // 判断方法是否有被 切点 匹配到
        System.out.println(pt2.matches(T1.class.getMethod("foo"),T1.class));
        System.out.println(pt2.matches(T1.class.getMethod("bar"),T1.class));

        System.out.println("==================");

        StaticMethodMatcherPointcut pt3 = new StaticMethodMatcherPointcut() {
            @Override
            public boolean matches(Method method, Class<?> targetClass) {
                // 检查方法上是否加了 Transactional 注解
                MergedAnnotations annotations = MergedAnnotations.from(method);
                if(annotations.isPresent(Transactional.class)){
                    return true;
                }
                // 查看类上是否加了 Transactional 注解
                annotations = MergedAnnotations.from(targetClass,MergedAnnotations.SearchStrategy.TYPE_HIERARCHY);
                if(annotations.isPresent(Transactional.class)){
                    return true;
                }
                return false;
            }
        };
        System.out.println(pt3.matches(T2.class.getMethod("foo"),T2.class));
        System.out.println(pt3.matches(T2.class.getMethod("bar"),T2.class));

        System.out.println("==========================");

        System.out.println(pt3.matches(T3.class.getMethod("foo"),T3.class));
        System.out.println(pt3.matches(T3.class.getMethod("bar"),T3.class));
    }

    static class T1{
        @Transactional
        public void foo(){

        }

        public void bar(){

        }
    }

    @Transactional
    static class T2{
        public void foo(){

        }

        public void bar(){

        }
    }

    @Transactional
    interface I3{

    }

    static class T3 implements I3{
        public void foo(){

        }

        public void bar(){

        }
    }
}
